package com.heyige.facade;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heyige.entity.User;
import com.heyige.entity.UserQuota;
import com.heyige.exception.BusinessException;
import com.heyige.exception.ErrorCode;
import com.heyige.mapper.UserMapper;
import com.heyige.mapper.UserQuotaMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserQuotaFacade {

    private final UserQuotaMapper userQuotaMapper;
    private final UserMapper userMapper;

    /**
     * 检查用户配额是否足够
     *
     * @param userId 用户ID
     * @param tokens 需要的token数量
     * @return 是否足够
     */
    public boolean checkQuota(Long userId, Integer tokens) {
        UserQuota userQuota = this.getUserQuota(userId);
        // 检查是否是VIP用户
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }
        // VIP用户不限制配额
        if (user.getIsVip() && user.getVipExpireTime() != null && user.getVipExpireTime().isAfter(LocalDateTime.now())) {
            return true;
        }
        // 检查配额是否足够
        return userQuota.getRemainingQuota() >= tokens;
    }

    /**
     * 扣除用户配额
     *
     * @param userId 用户ID
     * @param tokens 扣除的token数量
     */
    @Transactional(rollbackFor = Exception.class)
    public void deductQuota(Long userId, Integer tokens) {
        UserQuota userQuota = this.getUserQuota(userId);

        // 检查是否是VIP用户
        User user = userMapper.selectById(userId);
        if (null == user) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND);
        }

        // VIP用户不扣除配额
        if (user.getIsVip() && user.getVipExpireTime() != null && user.getVipExpireTime().isAfter(LocalDateTime.now())) {
            return;
        }
        // 检查配额是否足够
        if (userQuota.getRemainingQuota() < tokens) {
            throw new BusinessException(ErrorCode.USER_QUOTA_INSUFFICIENT);
        }
        // 扣除配额
        userQuota.setRemainingQuota(userQuota.getRemainingQuota() - tokens);
        userQuota.setUsedQuota(userQuota.getUsedQuota() + tokens);
        userQuota.setLastUsedTime(LocalDateTime.now());
        userQuotaMapper.insert(userQuota);
        log.info("用户 {} 扣除配额 {}，剩余配额 {}", userId, tokens, userQuota.getRemainingQuota());
    }

    /**
     * 增加用户配额
     *
     * @param userId 用户ID
     * @param tokens 增加的token数量
     */
    @Transactional(rollbackFor = Exception.class)
    public void addQuota(Long userId, Integer tokens) {
        UserQuota userQuota = this.getUserQuota(userId);
        userQuota.setRemainingQuota(userQuota.getRemainingQuota() + tokens);
        userQuotaMapper.insert(userQuota);
        log.info("用户 {} 增加配额 {}，剩余配额 {}", userId, tokens, userQuota.getRemainingQuota());
    }

    /**
     * 获取用户配额信息
     *
     * @param userId 用户ID
     * @return 用户配额信息
     */
    public UserQuota getUserQuota(Long userId) {
        UserQuota userQuota = userQuotaMapper.selectOne(new LambdaQueryWrapper<UserQuota>().eq(UserQuota::getUserId, userId));
        if (userQuota == null) {
            throw new BusinessException(ErrorCode.USER_QUOTA_NOT_EXISTS);
        }
        return userQuota;
    }

    /**
     * 重置用户配额（每日重置）
     *
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void resetDailyQuota(Long userId) {
        UserQuota userQuota = this.getUserQuota(userId);
        userQuota.setRemainingQuota(userQuota.getTotalQuota());
        userQuotaMapper.insert(userQuota);
        log.info("用户 {} 每日配额已重置", userId);
    }

    /**
     * 初始化用户配额
     *
     * @param userId     用户ID
     * @param totalQuota 总配额
     */
    @Transactional(rollbackFor = Exception.class)
    public void initializeQuota(Long userId, Integer totalQuota) {
        UserQuota userQuota = new UserQuota();
        userQuota.setUserId(userId);
        userQuota.setTotalQuota(totalQuota);
        userQuota.setRemainingQuota(totalQuota);
        userQuota.setUsedQuota(0);
        userQuotaMapper.insert(userQuota);
        log.info("用户 {} 配额已初始化，总配额 {}", userId, totalQuota);
    }

    /**
     * 更新用户总配额
     *
     * @param userId     用户ID
     * @param totalQuota 新的总配额
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateTotalQuota(Long userId, Integer totalQuota) {
        UserQuota userQuota = this.getUserQuota(userId);
        // 计算差值
        int diff = totalQuota - userQuota.getTotalQuota();
        userQuota.setTotalQuota(totalQuota);
        userQuota.setRemainingQuota(userQuota.getRemainingQuota() + diff);
        userQuotaMapper.insert(userQuota);
        log.info("用户 {} 总配额已更新为 {}，剩余配额 {}", userId, totalQuota, userQuota.getRemainingQuota());
    }

}